package processor;

import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import parser.*;

import static parser.MySimpleNode.jjtSetChild;
import static parser.MySimpleNode.jjtAppendChild;
import static parser.JoinHelp.changeFLWRtoJoin;

class Processor {
	public static void main(String args[]) {

		// ASTStart parseTree = setupParse(System.in);
		ASTStart parseTree = setupParse("query.txt");

//		 parseTree.dump("");

		 System.out.println("\n\n\n\n");
//		 rewriteJoins(parseTree);
//		 parseTree.dump("");

		//
		Document myDoc = buildDoc();
		List<Node> foobar = parseTree.process(myDoc);
		printDOMForest(foobar);
//		//
//		 System.out.println("\n\n\n\nDONE!");

	}

	private static void printDOMForest(List<Node> forest) {
		if (forest != null)
			for (Node n : forest)
				System.out.println(DOMPrinter.printXML(n));
	}

	private static void printDOMForest(List<Node> forest, String outFile) {
		try {
			// Create file
			FileWriter fstream = new FileWriter(outFile);
			BufferedWriter out = new BufferedWriter(fstream);

			if (forest != null)
				for (Node n : forest)
					out.write((DOMPrinter.printXML(n)));
			
			// Close the output stream
			out.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("Error: " + e.getMessage());
		}
	}

	// private static void testCreateJoinInnerLoop(ASTStart parseTree)
	// {
	// ASTXQueryFLWR inFLWR = (ASTXQueryFLWR) parseTree.jjtGetChild(0);
	// List<String> relVars = new ArrayList<String>();
	// relVars.add("$b1");
	// relVars.add("$aj");
	// relVars.add("$a1");
	// relVars.add("$af1");
	// relVars.add("$al1");
	// relVars.add("$af21");
	//
	// ASTXQueryFLWR newFLWR = JoinHelp.createJoinInnerLoop(inFLWR, relVars);
	// jjtSetChild(parseTree, newFLWR, 0);
	// parseTree.dump("");
	// }
	//
	// private static void testMakeOuterJoinReturn(ASTStart parseTree)
	// {
	// ASTXQueryFLWR inFLWR = (ASTXQueryFLWR) parseTree.jjtGetChild(0);
	// List<String> relVars = new ArrayList<String>();
	// relVars.add("$b1");
	// relVars.add("$aj");
	// relVars.add("$a1");
	// relVars.add("$af1");
	// relVars.add("$al1");
	// relVars.add("$af21");
	//
	// ASTXQueryFLWR newFLWR = JoinHelp.createJoinInnerLoop(inFLWR, relVars);
	// jjtSetChild(parseTree, newFLWR, 0);
	// parseTree.dump("");
	// }

	private static void rewriteJoins(ASTStart parseTree) {
		ASTXQueryFLWR inFLWR = (ASTXQueryFLWR) parseTree.jjtGetChild(0);
		changeFLWRtoJoin(inFLWR);
	}

	private static Document buildDoc() {
		// get an instance of factory
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		Document myDoc = null;
		try {
			// get an instance of builder
			DocumentBuilder db = dbf.newDocumentBuilder();
			// create an instance of DOM
			myDoc = db.newDocument();

		} catch (ParserConfigurationException pce) {
			// dump it
			System.out
					.println("Error while trying to instantiate DocumentBuilder "
							+ pce);
			System.exit(1);
		}
		return myDoc;
	}

	private static ASTStart setupParse(InputStream stream) {
		ASTStart parseTree = null;
		try {
			XQueryParser parser = new XQueryParser(stream);
			parseTree = (ASTStart) parser.Start();
		} catch (Exception e) {

			/*
			 * An exception occurred during parsing. Print the error message on
			 * standard output.
			 */
			System.out.println("---------------------------");
			System.out.println("Sorry, couldn't parse that.");
			System.out.println(e.getMessage());
			System.out.println("---------------------------");

			/*
			 * Print the call stack
			 */
			System.out.println("Call stack:");
			e.printStackTrace();
			System.out.println("---------------------------");

			System.exit(1);
		}
		return parseTree;
	}

	private static ASTStart setupParse(String fileName) {
		ASTStart retval = null;
		try {
			retval = setupParse(new FileInputStream(fileName));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return retval;
	}
}
